const express = require("express");
const router = express.Router();
const { SizeRule, User, sequelize } = require("../../models");
const { Op } = require("sequelize");
const { NotFound } = require("http-errors");
const { success, failure } = require("../../utils/responses");
const { userInfo } = require("../../utils/userInfo");

const { setSocket } = require("../../utils/msgSave");
const { getSocketInstance } = require("../../socket/socketInfo");
let socket = null;
/**
 * 查询尺寸列表
 * GET /admin/sizeRule
 */

router.get("/", async (req, res, next) => {
  try {
    const query = req.query;
    const currentPage = Math.abs(Number(query.currentPage)) || 1;
    const pageSize = Math.abs(Number(query.pageSize)) || 10;
    const offset = (currentPage - 1) * pageSize;

    const condition = {
      where: {},
      //      attributes: { exclude: ['UserId'] },
      // include: [
      //   {
      //     model: User,
      //     as: 'user',
      //     attributes: ['id', 'username']
      //   }
      // ],
      order: [["id", "DESC"]],
      limit: pageSize,
      offset: offset,
    };
    if (query.beUsed) {
      condition.where.beUsed = {
        [Op.like]: `%${query.beUsed.join(",")}%`,
      };
    }
    // 如果有long，查询long +-30的范围
    if (query.long) {
      condition.where.long = {
        [Op.between]: [
          (+query.long - 30).toString(),
          (+query.long + 30).toString(),
        ],
      };
    }
    const { count, rows } = await SizeRule.findAndCountAll(condition);

    success(req, res, "查询尺寸列表成功。", {
      list: rows,
      pagination: {
        total: count,
        currentPage,
        pageSize,
      },
    });
  } catch (error) {
    failure(req, res, error);
  }
});
/**
 * 查询尺寸列表详情
 * GET /admin/sizeRule
 */
router.get("/:id", async (req, res, next) => {
  try {
    const sizeRule = await getSizeRule(req);
    success(req, res, "查询尺寸成功。", {
      sizeRule,
    });
  } catch (error) {
    failure(req, res, error);
  }
});
/**
 * 更新尺寸
 * PUT /admin/sizeRule
 */
router.put("/:id", async (req, res, next) => {
  try {
    const sizeRule = await getSizeRule(req);
    const body = await filterBody(req);
    const validate = await validateBody(body);

    if (validate) {
      await sizeRule.update(body);
      const content = "更新尺寸成功";
      if (!socket) {
        socket = await getSocketInstance();
      }
      await setSocket(
        socket,
        "码垛信息",
        content,
        sizeRule.dataValues.userId,
        JSON.stringify(body)
      );

      success(req, res, content, {
        sizeRule,
      });
    }
  } catch (error) {
    failure(req, res, error);
  }
});

/**
 * 创建尺寸
 * POST /admin/sizeRule
 */
router.post("/", async (req, res, next) => {
  try {
    const body = await filterBody(req);
    const validate = await validateBody(body);
    if (validate) {
      const sizeRule = await SizeRule.create(body);
      const content = "创建尺寸成功";
      if (!socket) {
        socket = await getSocketInstance();
      }
      await setSocket(
        socket,
        "码垛信息",
        content,
        sizeRule.dataValues.userId,
        JSON.stringify(body)
      );

      success(req, res, content, {
        sizeRule,
      });
    }
  } catch (error) {
    failure(req, res, error);
  }
});
// 批量导入
router.post("/batch", async (req, res, next) => {
  try {
    const list = req.body.list;
    if (list.length == 0) {
      throw new NotFound("导入数据不能为空。");
    }
    const body = await filterBody(req, list);
    let reg = async () => {
      for (let i = 0; i < body.length; i++) {
        const validate = await validateBody(body[i]);
        if (!validate) {
          return false;
        }
      }
    };
    if (reg) {
      await sequelize.transaction(async (t) => {
        const sizeRuleList = body;
        await SizeRule.bulkCreate(sizeRuleList, {
          transaction: t,
        });
        const content = "批量导入尺寸成功。";
        if (!socket) {
          socket = await getSocketInstance();
        }
        await setSocket(
          socket,
          "码垛信息",
          content,
          body[0].userId,
          JSON.stringify(sizeRuleList)
        );

        success(req, res, content);
      });
    }
  } catch (error) {
    failure(req, res, error);
  }
});
/**
 * 删除尺寸表
 * DELETE /admin/sizeRules/:id
 */
router.delete("/:id", async (req, res, next) => {
  try {
    const sizeRule = await getSizeRule(req);
    await sizeRule.destroy();

    const content = "删除尺寸成功";
    if (!socket) {
      socket = await getSocketInstance();
    }
    await setSocket(
      socket,
      "码垛信息",
      content,
      sizeRule.dataValues.userId,
      "被删除的码垛尺寸id 是" + req.params.id
    );

    success(req, res, content);
  } catch (error) {
    failure(req, res, error);
  }
});

async function validateBody(body) {
  console.log("body====", body);

  const {
    long,
    wide,
    height,
    presetsNum,
    layerNum,
    palletizingNum,
    grippingDirection,
    leftAndRightFaultToleranceNum,
    faultToleranceBeforeAndAfterNum,
    beUsed,
    userId,
    userName,
  } = body;
  const numReg = /^\+?[1-9]\d*$/;
  if (!long) {
    throw new NotFound("长度不能为空。");
  }
  if (!numReg.test(long)) {
    throw new NotFound("长度必须为正整数。");
  }
  if (!wide) {
    throw new NotFound("宽度 不能为空。");
  }
  if (!numReg.test(wide)) {
    throw new NotFound("宽度必须为正整数。");
  }
  if (!height) {
    throw new NotFound("高度不能为空。");
  }
  if (!numReg.test(height)) {
    throw new NotFound("高度必须为正整数。");
  }
  if (!presetsNum) {
    throw new NotFound("码垛数量不能为空。");
  }
  if (!numReg.test(presetsNum)) {
    throw new NotFound("码垛数量必须为正整数。");
  }
  if (!layerNum) {
    throw new NotFound("每层件数不能为空。");
  }
  if (!numReg.test(layerNum)) {
    throw new NotFound("每层件数必须为正整数。");
  }
  if (!palletizingNum) {
    throw new NotFound("码垛层数不能为空。");
  }
  if (!numReg.test(palletizingNum)) {
    throw new NotFound("码垛层数必须为正整数。");
  }
  if (!grippingDirection) {
    throw new NotFound("grippingDirection 不能为空。");
  }
  if (!numReg.test(grippingDirection)) {
    throw new NotFound("夹抱方向必须为正整数。");
  }
  if (grippingDirection != 1 && grippingDirection != 2) {
    throw new NotFound("夹抱方向只能为1或2");
  }
  if (!leftAndRightFaultToleranceNum) {
    throw new NotFound("左右容错不能为空。");
  }
  if (!numReg.test(leftAndRightFaultToleranceNum)) {
    throw new NotFound("左右容错必须为正整数。");
  }
  if (!faultToleranceBeforeAndAfterNum) {
    throw new NotFound("前后容错不能为空。");
  }
  if (!numReg.test(faultToleranceBeforeAndAfterNum)) {
    throw new NotFound("前后容错必须为正整数。");
  }

  if (!beUsed) {
    throw new NotFound("beUsed 不能为空。");
  }
  if (beUsed) {
    const beUsedAry = beUsed.split(",");
    for (let index = 0; index < beUsedAry.length; index++) {
      const element = beUsedAry[index];
      console.log("element", element);

      if (
        element / 1 !== 1 &&
        element / 1 !== 2 &&
        element / 1 !== 3 &&
        element / 1 !== 4
      ) {
        throw new NotFound("应用只能是 1或2或3或4。");
      }
    }
  }
  if (!userId) {
    throw new NotFound("userId 不能为空。");
  }
  if (!userName) {
    throw new NotFound("userName 不能为空。");
  }

  return true;
}

/**
 * 公共方法：查询当前尺寸表
 */
async function getSizeRule(req) {
  const { id } = req.params;

  const sizeRule = await SizeRule.findByPk(id);

  if (!sizeRule) {
    throw new NotFound(`ID: ${id}的尺寸表未找到。`);
  }

  return sizeRule;
}

/**
 * 公共方法：白名单过滤
 * @param req
 * @returns
 */
async function filterBody(req, list = []) {
  let { user, originname } = await userInfo(req);
  if (list.length > 0) {
    for (let i = 0; i < list.length; i++) {
      list[i].userId = user.id;
      list[i].userName = user.username;
    }
    return list;
  }

  return {
    long: req.body.long,
    wide: req.body.wide,
    height: req.body.height,
    presetsNum: req.body.presetsNum,
    layerNum: req.body.layerNum,
    palletizingNum: req.body.palletizingNum,
    grippingDirection: req.body.grippingDirection,
    leftAndRightFaultToleranceNum: req.body.leftAndRightFaultToleranceNum,
    faultToleranceBeforeAndAfterNum: req.body.faultToleranceBeforeAndAfterNum,
    userId: user.id,
    userName: user.username,
    beUsed: req.body.beUsed,
  };
}

module.exports = router;
